//
//  BLEDataConverter.m
//  BLESDK
//
//  Created on Desktop.
//

#import "BLEDataConverter.h"

@implementation BLEDataConverter

#pragma mark - Hex String Conversions

+ (nullable NSData *)dataFromHexString:(NSString *)hexString {
    if (!hexString || [hexString length] == 0) {
        return nil;
    }
    
    // 去除空格和其他非十六进制字符
    NSCharacterSet *characterSet = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEFabcdef"] invertedSet];
    NSString *cleanedHexString = [[hexString componentsSeparatedByCharactersInSet:characterSet] componentsJoinedByString:@""];
    
    // 确保字符串长度为偶数
    if ([cleanedHexString length] % 2 != 0) {
        cleanedHexString = [NSString stringWithFormat:@"0%@", cleanedHexString];
    }
    
    NSMutableData *data = [NSMutableData dataWithCapacity:[cleanedHexString length] / 2];
    for (NSUInteger i = 0; i < [cleanedHexString length]; i += 2) {
        NSRange range = NSMakeRange(i, 2);
        NSString *byteString = [cleanedHexString substringWithRange:range];
        uint8_t byte = 0;
        [[NSScanner scannerWithString:byteString] scanHexInt:&byte];
        [data appendBytes:&byte length:1];
    }
    
    return data;
}

+ (NSString *)hexStringFromData:(NSData *)data uppercase:(BOOL)uppercase {
    if (!data || [data length] == 0) {
        return @"";
    }
    
    NSMutableString *hexString = [NSMutableString string];
    const uint8_t *bytes = [data bytes];
    
    for (NSUInteger i = 0; i < [data length]; i++) {
        if (uppercase) {
            [hexString appendFormat:@"%02X", bytes[i]];
        } else {
            [hexString appendFormat:@"%02x", bytes[i]];
        }
    }
    
    return [hexString copy];
}

+ (NSString *)hexStringFromData:(NSData *)data {
    return [self hexStringFromData:data uppercase:YES];
}

#pragma mark - ASCII Conversions

+ (nullable NSString *)asciiStringFromHexString:(NSString *)hexString {
    NSData *data = [self dataFromHexString:hexString];
    if (!data) {
        return nil;
    }
    
    return [self asciiStringFromData:data];
}

+ (NSString *)hexStringFromASCIIString:(NSString *)asciiString uppercase:(BOOL)uppercase {
    if (!asciiString || [asciiString length] == 0) {
        return @"";
    }
    
    NSData *data = [self dataFromASCIIString:asciiString];
    return [self hexStringFromData:data uppercase:uppercase];
}

+ (NSString *)asciiStringFromData:(NSData *)data {
    if (!data || [data length] == 0) {
        return @"";
    }
    
    // 创建一个以null结尾的数据，确保字符串初始化有效
    NSMutableData *mutableData = [NSMutableData dataWithData:data];
    [mutableData appendBytes:"\0" length:1];
    
    return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] ?: @"";
}

+ (NSData *)dataFromASCIIString:(NSString *)asciiString {
    if (!asciiString) {
        return [NSData data];
    }
    
    return [asciiString dataUsingEncoding:NSASCIIStringEncoding] ?: [NSData data];
}

#pragma mark - Integer Conversions

+ (NSData *)dataWithIntValue:(NSInteger)value length:(NSUInteger)length {
    return [self dataWithIntValue:value length:length bigEndian:NO];
}

+ (NSData *)dataWithIntValue:(NSInteger)value length:(NSUInteger)length bigEndian:(BOOL)bigEndian {
    if (length == 0 || length > sizeof(NSInteger)) {
        return [NSData data];
    }
    
    NSMutableData *data = [NSMutableData dataWithLength:length];
    uint8_t *bytes = [data mutableBytes];
    
    if (bigEndian) {
        // 大端序：高位字节在低地址
        for (NSUInteger i = 0; i < length; i++) {
            bytes[i] = (value >> (8 * (length - 1 - i))) & 0xFF;
        }
    } else {
        // 小端序：低位字节在低地址
        for (NSUInteger i = 0; i < length; i++) {
            bytes[i] = (value >> (8 * i)) & 0xFF;
        }
    }
    
    return data;
}

+ (NSInteger)intValueFromData:(NSData *)data startIndex:(NSUInteger)startIndex length:(NSUInteger)length {
    return [self intValueFromData:data startIndex:startIndex length:length bigEndian:NO];
}

+ (NSInteger)intValueFromData:(NSData *)data startIndex:(NSUInteger)startIndex length:(NSUInteger)length bigEndian:(BOOL)bigEndian {
    if (!data || startIndex + length > [data length] || length > sizeof(NSInteger)) {
        return 0;
    }
    
    const uint8_t *bytes = [data bytes];
    NSInteger value = 0;
    
    if (bigEndian) {
        // 大端序：高位字节在低地址
        for (NSUInteger i = 0; i < length; i++) {
            value = (value << 8) | bytes[startIndex + i];
        }
    } else {
        // 小端序：低位字节在低地址
        for (NSUInteger i = 0; i < length; i++) {
            value |= ((NSInteger)bytes[startIndex + i]) << (8 * i);
        }
    }
    
    return value;
}

#pragma mark - Float Conversions

+ (NSData *)dataWithFloat:(float)floatValue bigEndian:(BOOL)bigEndian {
    uint32_t intBits;
    memcpy(&intBits, &floatValue, sizeof(float));
    
    return [self dataWithIntValue:intBits length:sizeof(float) bigEndian:bigEndian];
}

+ (float)floatFromData:(NSData *)data startIndex:(NSUInteger)startIndex bigEndian:(BOOL)bigEndian {
    if (!data || startIndex + sizeof(float) > [data length]) {
        return 0.0f;
    }
    
    uint32_t intBits = (uint32_t)[self intValueFromData:data startIndex:startIndex length:sizeof(float) bigEndian:bigEndian];
    float floatValue;
    memcpy(&floatValue, &intBits, sizeof(float));
    
    return floatValue;
}

#pragma mark - Data Manipulation

+ (NSData *)combineData:(NSData *)firstData, ... {
    if (!firstData) {
        return [NSData data];
    }
    
    NSMutableData *result = [NSMutableData dataWithData:firstData];
    
    va_list args;
    va_start(args, firstData);
    
    NSData *data;
    while ((data = va_arg(args, NSData *))) {
        [result appendData:data];
    }
    
    va_end(args);
    
    return result;
}

+ (NSData *)combineDataArray:(NSArray<NSData *> *)dataArray {
    if (!dataArray || [dataArray count] == 0) {
        return [NSData data];
    }
    
    NSMutableData *result = [NSMutableData data];
    for (NSData *data in dataArray) {
        if (data) {
            [result appendData:data];
        }
    }
    
    return result;
}

+ (nullable NSData *)subDataWithData:(NSData *)data range:(NSRange)range {
    if (!data || range.location + range.length > [data length]) {
        return nil;
    }
    
    return [data subdataWithRange:range];
}

@end 